﻿
#include <iostream>
#include<boost/asio.hpp>
#include<thread>
#include<json/json.h>
#include<json/value.h>
#include<json/reader.h>
#include<chrono>//打印问题处理的时间
using namespace std;
using namespace boost::asio::ip;
const int MAX_LENGTH = 1024 * 2;
const int HEAD_LENGTH = 2;
const int HEAD_TOTAL = 4;

vector<thread> vec_threads;//每个线程处理收发
int main()
{
    auto start = std::chrono::high_resolution_clock::now();//现在开启的时间
    for (int i = 0; i < 100; i++) {
        //建立100个连接
        vec_threads.emplace_back([]() {
            try {
                boost::asio::io_context ioc;
                tcp::endpoint remote_ep(address::from_string("127.0.0.1"), 10086);
                tcp::socket sock(ioc);//拿socket绑定上下文服务后去和对端通信
                boost::system::error_code error = boost::asio::error::host_not_found;
                sock.connect(remote_ep, error);

                if (error) {
                    cout << "connect failed,code is:" << error.value() << "error is:" << error.message();
                    return 0;

                }
                int i = 0;
                while (i < 500) {//每个线程建立连接后循环收发数据500次
                    Json::Value root;
                    root["id"] = 1001;
                    root["data"] = "hello world";
                    std::string request = root.toStyledString();//序列化
                    size_t request_length = request.length();
                    char send_data[MAX_LENGTH] = { 0 };
                    int msgid = 1001;//这里把id写死了
                    int msgid_host = boost::asio::detail::socket_ops::host_to_network_short(msgid);
                    memcpy(send_data, &msgid_host, 2);//存id
                    //转为网络字节序
                    int request_host_length = boost::asio::detail::socket_ops::host_to_network_short(request_length);
                    memcpy(send_data + 2, &request_host_length, 2);//存长度
                    memcpy(send_data + 4, request.c_str(), request_length);//存信息

                    boost::asio::write(sock, boost::asio::buffer(send_data, request_length + 4));//序列化信息写入并发送给对端
                    cout << "begin to receive..." << endl;

                    char reply_head[HEAD_TOTAL];
                    size_t reply_length = boost::asio::read(sock, boost::asio::buffer(reply_head, HEAD_TOTAL));//read是接受到指定字节才会触发回调,非常方便
                    msgid = 0;
                    memcpy(&msgid, reply_head, HEAD_LENGTH);

                    short msglen = 0;
                    memcpy(&msglen, reply_head + 2, HEAD_LENGTH);
                    //转为本地字节序
                    msgid = boost::asio::detail::socket_ops::network_to_host_short(msgid);
                    msglen = boost::asio::detail::socket_ops::network_to_host_short(msglen);
                    char msg[MAX_LENGTH] = { 0 };
                    size_t msg_length = boost::asio::read(sock, boost::asio::buffer(msg, msglen));
                    Json::Reader reader;
                    reader.parse(std::string(msg, msg_length), root);
                    std::cout << "msg id is:" << root["id"] << "msg is:" << root["data"] << endl;
                    i++;
                }
            }
            catch (std::exception& e) {
                std::cerr << "EXCEPTION:" << e.what() << endl;
            }
            });
        std::this_thread::sleep_for(std::chrono::milliseconds(10));//每次循环后都睡一会防止对服务器进行洪水攻击每隔十毫秒启动一个线程
    }
    for (auto& t : vec_threads) {
        t.join();
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    cout << "Time spent" << duration.count() << "microseconds" << std::endl;
    getchar();
    return 0;
}
